//+------------------------------------------------------------------+
//|                                                      junxian.mq5 |
//|                                  Copyright 2025, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2025, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"

//--- 输入参数
input ulong   InpMagicNumber  = 88888;    // EA魔术棒
input int     InpMA1Period    = 100;       // 第一条均线周期
input int     InpMA2Period    = 300;       // 第二条均线周期
input int     InpMA3Period    = 600;       // 第三条均线周期
input color   InpMA1Color     = clrBlue;  // 第一条均线颜色
input color   InpMA2Color     = clrRed;   // 第二条均线颜色
input color   InpMA3Color     = clrGreen; // 第三条均线颜色
input int     InpMA1Width     = 2;        // 第一条均线粗细
input int     InpMA2Width     = 2;        // 第二条均线粗细
input int     InpMA3Width     = 2;        // 第三条均线粗细

//--- 顺势加仓策略参数
input double  InpAddPipsDistance   = 3000.0;    // 加仓距离(点)
input double  InpLotSize           = 0.01;    // 初始手数
input double  InpAddLotSize        = 0.01;    // 加仓手数
input int     InpMaxAdditions      = 20;      // 最大加仓次数

//--- 平仓条件参数
input double  InpLossLevel1        = 10.0;    // 第一档亏损金额(美元)
input double  InpLossTotal1        = 0.01;    // 第一档最大手数

input double  InpLossLevel2        = 10.0;    // 第二档亏损金额(美元)
input double  InpLossTotal2        = 0.02;    // 第二档最大手数

input double  InpLossLevel3        = 1.0;    // 第三档亏损金额(美元)
input double  InpLossTotal3        = 0.03;    // 第三档最大手数

input double  InpProfitRetrace     = 60.0;    // 利润回吐百分比(%)
input double  InpTakeProfit        = 2000.0;   // 止盈金额(美元) - 新增参数

//--- 全局变量
int    ma1_handle, ma2_handle, ma3_handle;
int    last_pattern = -1;      // 最近一次排列模式: 1=多头, 0=空头, -1=未定义
int    last_bar_count = 0;     // 上一次计算的柱数
string current_symbol;

//--- 顺势加仓相关变量
double base_price = 0.0;       // 基准价格
int    addition_count = 0;     // 当前加仓次数
double total_lots = 0.0;       // 总手数
double peak_profit = 0.0;      // 峰值利润(用于利润回吐计算)
bool   initial_trade_opened = false; // 初始交易是否已开启

#define MAX_BARS_TO_CHECK 10000  // OnInit进来最大检查历史柱数
#define MAX_BARS_TO_PLOT   10000  // 最大绘制均线柱数
#define UPDATE_BARS_COUNT   10  // 每次更新的柱数

ENUM_TIMEFRAMES current_timeframe;

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
{
//--- 获取当前图表品种和周期
   current_symbol = _Symbol;
   current_timeframe = _Period;
   
//--- 创建均线指标句柄
   ma1_handle = iMA(current_symbol, current_timeframe, InpMA1Period, 0, MODE_SMA, PRICE_CLOSE);
   ma2_handle = iMA(current_symbol, current_timeframe, InpMA2Period, 0, MODE_SMA, PRICE_CLOSE);
   ma3_handle = iMA(current_symbol, current_timeframe, InpMA3Period, 0, MODE_SMA, PRICE_CLOSE);
   
//--- 检查句柄是否创建成功
   if(ma1_handle == INVALID_HANDLE || ma2_handle == INVALID_HANDLE || ma3_handle == INVALID_HANDLE)
   {
      Print("错误: 未能创建指标句柄");
      return(INIT_FAILED);
   }
   
//--- 绘制均线
   PlotMAOnChart();
   
//--- 初始计算一次排列状态
   CheckPatternOnNewBar(MAX_BARS_TO_CHECK);
   
//--- 初始化顺势加仓变量
   base_price = SymbolInfoDouble(current_symbol, SYMBOL_BID);
   addition_count = 0;
   total_lots = 0.0;
   peak_profit = 0.0;
   initial_trade_opened = false;
   
   return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
//--- 删除绘制的均线对象
   DeleteMAObjects();
   
//--- 释放指标句柄
   if(ma1_handle != INVALID_HANDLE) IndicatorRelease(ma1_handle);
   if(ma2_handle != INVALID_HANDLE) IndicatorRelease(ma2_handle);
   if(ma3_handle != INVALID_HANDLE) IndicatorRelease(ma3_handle);
}
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
{
//--- 只在有新柱形成时进行检查
   if(IsNewBar())
   {
      CheckPatternOnNewBar(100);
      UpdateMAOnChart(); // 更新均线显示
      
      // 检查是否需要开立初始仓位
      CheckInitialTrade();
   }
   
//--- 执行顺势加仓策略
   ExecuteTrendAdditionStrategy();
   
//--- 检查止盈条件（每次tick都检查）
   CheckTakeProfit();
}
//+------------------------------------------------------------------+
//| 检查止盈条件                                                     |
//+------------------------------------------------------------------+
void CheckTakeProfit()
{
//--- 如果有持仓且设置了止盈金额
   if(CountPositions() > 0 && InpTakeProfit > 0)
   {
      // 计算当前总盈利
      double current_profit = CalculateTotalProfit();
      
      // 如果盈利达到或超过止盈金额
      if(current_profit >= InpTakeProfit)
      {
         CloseAllPositions();
         Print("止盈条件触发，盈利: ", current_profit, "，达到止盈金额: ", InpTakeProfit);
      }
   }
}
//+------------------------------------------------------------------+
//| 检查是否需要开立初始仓位                                         |
//+------------------------------------------------------------------+
void CheckInitialTrade()
{
//--- 如果没有持仓且有明确的趋势方向，开立初始仓位
   if(CountPositions() == 0 && last_pattern != -1 && !initial_trade_opened)
   {
      if(last_pattern == 1) // 多头趋势
      {
         if(OpenBuyPosition(InpLotSize))
         {
            addition_count = 1;
            total_lots = InpLotSize;
            base_price = SymbolInfoDouble(current_symbol, SYMBOL_BID);
            initial_trade_opened = true;
            Print("初始多头开仓，手数: ", total_lots);
         }
      }
      else if(last_pattern == 0) // 空头趋势
      {
         if(OpenSellPosition(InpLotSize))
         {
            addition_count = 1;
            total_lots = InpLotSize;
            base_price = SymbolInfoDouble(current_symbol, SYMBOL_ASK);
            initial_trade_opened = true;
            Print("初始空头开仓，手数: ", total_lots);
         }
      }
   }
   else if(CountPositions() == 0)
   {
      initial_trade_opened = false;
   }
}
//+------------------------------------------------------------------+
//| 执行顺势加仓策略                                                 |
//+------------------------------------------------------------------+
void ExecuteTrendAdditionStrategy()
{
//--- 检查是否有本EA的持仓
   if(CountPositions() == 0)
   {
      // 没有持仓，重置加仓状态
      addition_count = 0;
      total_lots = 0.0;
      peak_profit = 0.0;
      initial_trade_opened = false;
      base_price = SymbolInfoDouble(current_symbol, (last_pattern == 1) ? SYMBOL_BID : SYMBOL_ASK);
      return;
   }
   
//--- 获取当前价格
   double current_price = SymbolInfoDouble(current_symbol, (last_pattern == 1) ? SYMBOL_BID : SYMBOL_ASK);
   
//--- 根据趋势方向执行加仓逻辑
   if(last_pattern == 1) // 多头趋势
   {
      // 检查是否需要加仓
      if(current_price >= base_price + addition_count * InpAddPipsDistance * _Point * 10)
      {
         if(addition_count < InpMaxAdditions)
         {
            // 执行加仓
            if(OpenBuyPosition(InpAddLotSize))
            {
               addition_count++;
               total_lots += InpAddLotSize;
               Print("多头加仓 #", addition_count, ", 总手数: ", total_lots);
            }
         }
      }
      
      // 检查平仓条件
      CheckCloseConditions();
   }
   else if(last_pattern == 0) // 空头趋势
   {
      // 检查是否需要加仓
      if(current_price <= base_price - addition_count * InpAddPipsDistance * _Point * 10)
      {
         if(addition_count < InpMaxAdditions)
         {
            // 执行加仓
            if(OpenSellPosition(InpAddLotSize))
            {
               addition_count++;
               total_lots += InpAddLotSize;
               Print("空头加仓 #", addition_count, ", 总手数: ", total_lots);
            }
         }
      }
      
      // 检查平仓条件
      CheckCloseConditions();
   }
}
//+------------------------------------------------------------------+
//| 检查平仓条件                                                     |
//+------------------------------------------------------------------+
void CheckCloseConditions()
{
//--- 获取当前持仓总盈亏
   double current_profit = CalculateTotalProfit();
   
//--- 更新峰值利润
   if(current_profit > peak_profit)
      peak_profit = current_profit;
   
//--- 分档检查平仓条件
   if(total_lots <= InpLossTotal1) // 第一档
   {
      if(current_profit <= -InpLossLevel1)
      {
         CloseAllPositions();
         Print("第一档平仓条件触发，亏损: ", current_profit);
      }
   }
   else if(total_lots <= InpLossTotal2) // 第二档
   {
      if(current_profit <= -InpLossLevel2)
      {
         CloseAllPositions();
         Print("第二档平仓条件触发，亏损: ", current_profit);
      }
   }
   else if(total_lots <= InpLossTotal3) // 第三档
   {
      if(current_profit <= -InpLossLevel3)
      {
         CloseAllPositions();
         Print("第三档平仓条件触发，亏损: ", current_profit);
      }
   }
   else // 第四档
   {
      // 检查利润回吐
      if(peak_profit > 0 && current_profit <= peak_profit * (1 - InpProfitRetrace/100))
      {
         CloseAllPositions();
         Print("第四档平仓条件触发，利润回吐: ", current_profit, ", 峰值: ", peak_profit);
      }
   }
}
//+------------------------------------------------------------------+
//| 计算本EA所有持仓的总盈亏                                         |
//+------------------------------------------------------------------+
double CalculateTotalProfit()
{
   double total_profit = 0.0;
   
   for(int i = PositionsTotal()-1; i >= 0; i--)
   {
      ulong ticket = PositionGetTicket(i);
      if(PositionGetInteger(POSITION_MAGIC) == InpMagicNumber && 
         PositionGetString(POSITION_SYMBOL) == current_symbol)
      {
         total_profit += PositionGetDouble(POSITION_PROFIT);
      }
   }
   
   return total_profit;
}
//+------------------------------------------------------------------+
//| 统计本EA的持仓数量                                               |
//+------------------------------------------------------------------+
int CountPositions()
{
   int count = 0;
   
   for(int i = PositionsTotal()-1; i >= 0; i--)
   {
      ulong ticket = PositionGetTicket(i);
      if(PositionGetInteger(POSITION_MAGIC) == InpMagicNumber && 
         PositionGetString(POSITION_SYMBOL) == current_symbol)
      {
         count++;
      }
   }
   
   return count;
}
bool OpenBuyPosition(double lots)
{
   MqlTradeRequest request;
   MqlTradeResult result;
   ZeroMemory(request);
   ZeroMemory(result);
   
   // 计算点差并调整开仓价格
   double ask = SymbolInfoDouble(current_symbol, SYMBOL_ASK);
   double point = SymbolInfoDouble(current_symbol, SYMBOL_POINT);
   long spread = SymbolInfoInteger(current_symbol, SYMBOL_SPREAD);
   
   request.action = TRADE_ACTION_DEAL;
   request.symbol = current_symbol;
   request.volume = lots;
   request.type = ORDER_TYPE_BUY;
   request.price = ask;
   request.magic = InpMagicNumber;
   request.comment = "Trend Addition Buy";
   
   // 设置止损止盈（可选）
   // request.sl = 0;
   // request.tp = 0;
   
   if(OrderSend(request, result))
   {
      Print("开多头仓位成功，手数: ", lots, ", 价格: ", request.price);
      return true;
   }
   else
   {
      Print("开多头仓位失败，错误代码: ", GetLastError());
      return false;
   }
}
//+------------------------------------------------------------------+
//| 开空头仓位                                                       |
//+------------------------------------------------------------------+
bool OpenSellPosition(double lots)
{
   MqlTradeRequest request;
   MqlTradeResult result;
   ZeroMemory(request);
   ZeroMemory(result);
   
   // 计算点差并调整开仓价格
   double bid = SymbolInfoDouble(current_symbol, SYMBOL_BID);
   double point = SymbolInfoDouble(current_symbol, SYMBOL_POINT);
   long spread = SymbolInfoInteger(current_symbol, SYMBOL_SPREAD);
   
   request.action = TRADE_ACTION_DEAL;
   request.symbol = current_symbol;
   request.volume = lots;
   request.type = ORDER_TYPE_SELL;
   request.price = bid;
   request.magic = InpMagicNumber;
   request.comment = "Trend Addition Sell";
   
   // 设置止损止盈（可选）
   // request.sl = 0;
   // request.tp = 0;
   
   if(OrderSend(request, result))
   {
      Print("开空头仓位成功，手数: ", lots, ", 价格: ", request.price);
      return true;
   }
   else
   {
      Print("开空头仓位失败，错误代码: ", GetLastError());
      return false;
   }
}
//+------------------------------------------------------------------+
//| 平掉所有本EA的仓位                                               |
//+------------------------------------------------------------------+
void CloseAllPositions()
{
   for(int i = PositionsTotal()-1; i >= 0; i--)
   {
      ulong ticket = PositionGetTicket(i);
      if(PositionGetInteger(POSITION_MAGIC) == InpMagicNumber && 
         PositionGetString(POSITION_SYMBOL) == current_symbol)
      {
         MqlTradeRequest request;
         MqlTradeResult result;
         ZeroMemory(request);
         ZeroMemory(result);
         
         request.action = TRADE_ACTION_DEAL;
         request.position = ticket;
         request.symbol = current_symbol;
         request.volume = PositionGetDouble(POSITION_VOLUME);
         request.magic = InpMagicNumber;
         
         if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY)
         {
            request.type = ORDER_TYPE_SELL;
            request.price = SymbolInfoDouble(current_symbol, SYMBOL_BID);
         }
         else
         {
            request.type = ORDER_TYPE_BUY;
            request.price = SymbolInfoDouble(current_symbol, SYMBOL_ASK);
         }
         
         if(OrderSend(request, result))
         {
            Print("平仓成功，仓位: ", ticket);
         }
         else
         {
            Print("平仓失败，仓位: ", ticket, ", 错误代码: ", GetLastError());
         }
      }
   }
   
   // 重置加仓状态
   addition_count = 0;
   total_lots = 0.0;
   peak_profit = 0.0;
   initial_trade_opened = false;
   base_price = SymbolInfoDouble(current_symbol, (last_pattern == 1) ? SYMBOL_BID : SYMBOL_ASK);
}
//+------------------------------------------------------------------+
//| 检查是否有新柱形成                                                |
//+------------------------------------------------------------------+
bool IsNewBar()
{
   static datetime last_time = 0;
   datetime current_time = iTime(current_symbol, current_timeframe, 0);
   
   if(last_time != current_time)
   {
      last_time = current_time;
      return true;
   }
   return false;
}
//+------------------------------------------------------------------+
//| 在新柱上检查排列模式                                              |
//+------------------------------------------------------------------+
void CheckPatternOnNewBar(int CheckK)
{
//--- 获取当前柱数
   int bars = Bars(current_symbol, current_timeframe);
   if(bars <= 0) return;
   
//--- 限制复制的数据量以提高性能
   int copy_count = MathMin(bars, CheckK); // 最多检查MAX_BARS_TO_CHECK根柱
   int start_pos = 0; // 从当前柱开始
   
//--- 准备数组存储均线数据
   double ma1_buf[], ma2_buf[], ma3_buf[];
   ArraySetAsSeries(ma1_buf, true);
   ArraySetAsSeries(ma2_buf, true);
   ArraySetAsSeries(ma3_buf, true);
   
//--- 复制均线数据
   if(CopyBuffer(ma1_handle, 0, start_pos, copy_count, ma1_buf) < copy_count ||
      CopyBuffer(ma2_handle, 0, start_pos, copy_count, ma2_buf) < copy_count ||
      CopyBuffer(ma3_handle, 0, start_pos, copy_count, ma3_buf) < copy_count)
   {
      Print("错误: 未能复制指标数据");
      return;
   }
   
//--- 从最新数据开始遍历寻找最近的排列模式
   for(int i = 0; i < copy_count; i++)
   {
      // 跳过无效数据
      if(ma1_buf[i] == EMPTY_VALUE || ma2_buf[i] == EMPTY_VALUE || ma3_buf[i] == EMPTY_VALUE)
         continue;
         
      // 检查多头排列: MA20 > MA30 > MA40
      if(ma1_buf[i] > ma2_buf[i] && ma2_buf[i] > ma3_buf[i])
      {
         last_pattern = 1;
         break;
      }
      // 检查空头排列: MA20 < MA30 < MA40
      else if(ma1_buf[i] < ma2_buf[i] && ma2_buf[i] < ma3_buf[i])
      {
         last_pattern = 0;
         break;
      }
   }
   
//--- 输出当前排列状态（可选，用于调试）
   Print("当前均线排列: ", (last_pattern == 1 ? "多头" : (last_pattern == 0 ? "空头" : "未定义")));
}
//+------------------------------------------------------------------+
//| 绘制均线到图表上                                                  |
//+------------------------------------------------------------------+
void PlotMAOnChart()
{
//--- 删除可能存在的旧对象
   DeleteMAObjects();
   
//--- 获取最近MAX_BARS_TO_PLOT根柱的均线值
   double ma1_values[], ma2_values[], ma3_values[];
   ArraySetAsSeries(ma1_values, true);
   ArraySetAsSeries(ma2_values, true);
   ArraySetAsSeries(ma3_values, true);
   
   int bars = MathMin(Bars(current_symbol, current_timeframe), MAX_BARS_TO_PLOT);
   
   if(CopyBuffer(ma1_handle, 0, 0, bars, ma1_values) < bars ||
      CopyBuffer(ma2_handle, 0, 0, bars, ma2_values) < bars ||
      CopyBuffer(ma3_handle, 0, 0, bars, ma3_values) < bars)
   {
      Print("错误: 无法复制均线数据用于绘制");
      return;
   }
   
//--- 创建均线对象
   for(int i = 0; i < bars - 1; i++)
   {
      // 第一条均线
      string name1 = "MA1_"+IntegerToString(i);
      ObjectCreate(0, name1, OBJ_TREND, 0, iTime(current_symbol, current_timeframe, i), ma1_values[i], 
                   iTime(current_symbol, current_timeframe, i+1), ma1_values[i+1]);
      ObjectSetInteger(0, name1, OBJPROP_COLOR, InpMA1Color);
      ObjectSetInteger(0, name1, OBJPROP_WIDTH, InpMA1Width);
      ObjectSetInteger(0, name1, OBJPROP_RAY_LEFT, false);
      
      // 第二条均线
      string name2 = "MA2_"+IntegerToString(i);
      ObjectCreate(0, name2, OBJ_TREND, 0, iTime(current_symbol, current_timeframe, i), ma2_values[i], 
                   iTime(current_symbol, current_timeframe, i+1), ma2_values[i+1]);
      ObjectSetInteger(0, name2, OBJPROP_COLOR, InpMA2Color);
      ObjectSetInteger(0, name2, OBJPROP_WIDTH, InpMA2Width);
      ObjectSetInteger(0, name2, OBJPROP_RAY_LEFT, false);
      
      // 第三条均线
      string name3 = "MA3_"+IntegerToString(i);
      ObjectCreate(0, name3, OBJ_TREND, 0, iTime(current_symbol, current_timeframe, i), ma3_values[i], 
                   iTime(current_symbol, current_timeframe, i+1), ma3_values[i+1]);
      ObjectSetInteger(0, name3, OBJPROP_COLOR, InpMA3Color);
      ObjectSetInteger(0, name3, OBJPROP_WIDTH, InpMA3Width);
      ObjectSetInteger(0, name3, OBJPROP_RAY_LEFT, false);
   }
}
//+------------------------------------------------------------------+
//| 更新图表上的均线显示                                              |
//+------------------------------------------------------------------+
void UpdateMAOnChart()
{
//--- 只更新最近几根柱的均线显示以提高性能
   int update_bars = UPDATE_BARS_COUNT; // 只更新最近10根柱
   
//--- 获取最近数据
   double ma1_values[], ma2_values[], ma3_values[];
   ArraySetAsSeries(ma1_values, true);
   ArraySetAsSeries(ma2_values, true);
   ArraySetAsSeries(ma3_values, true);
   
   if(CopyBuffer(ma1_handle, 0, 0, update_bars, ma1_values) < update_bars ||
      CopyBuffer(ma2_handle, 0, 0, update_bars, ma2_values) < update_bars ||
      CopyBuffer(ma3_handle, 0, 0, update_bars, ma3_values) < update_bars)
   {
      return;
   }
   
//--- 更新均线对象
   for(int i = 0; i < update_bars - 1; i++)
   {
      // 第一条均线
      string name1 = "MA1_"+IntegerToString(i);
      if(ObjectFind(0, name1) >= 0)
      {
         ObjectMove(0, name1, 0, iTime(current_symbol, current_timeframe, i), ma1_values[i]);
         ObjectMove(0, name1, 1, iTime(current_symbol, current_timeframe, i+1), ma1_values[i+1]);
      }
      
      // 第二条均线
      string name2 = "MA2_"+IntegerToString(i);
      if(ObjectFind(0, name2) >= 0)
      {
         ObjectMove(0, name2, 0, iTime(current_symbol, current_timeframe, i), ma2_values[i]);
         ObjectMove(0, name2, 1, iTime(current_symbol, current_timeframe, i+1), ma2_values[i+1]);
      }
      
      // 第三条均线
      string name3 = "MA3_"+IntegerToString(i);
      if(ObjectFind(0, name3) >= 0)
      {
         ObjectMove(0, name3, 0, iTime(current_symbol, current_timeframe, i), ma3_values[i]);
         ObjectMove(0, name3, 1, iTime(current_symbol, current_timeframe, i+1), ma3_values[i+1]);
      }
   }
}
//+------------------------------------------------------------------+
//| 删除所有均线对象                                                  |
//+------------------------------------------------------------------+
void DeleteMAObjects()
{
//--- 删除所有以"MA1_", "MA2_", "MA3_"开头的对象
   for(int i = ObjectsTotal(0) - 1; i >= 0; i--)
   {
      string name = ObjectName(0, i);
      if(StringFind(name, "MA1_") == 0 || 
         StringFind(name, "MA2_") == 0 || 
         StringFind(name, "MA3_") == 0)
      {
         ObjectDelete(0, name);
      }
   }
}
//+------------------------------------------------------------------+